package top.wshape1.shiziapi.project.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.wshape1.shiziapi.common.constant.RedisConstant;
import top.wshape1.shiziapi.common.domain.ProjectSearch;
import top.wshape1.shiziapi.project.config.RabbitMqConfig;
import top.wshape1.shiziapi.project.domain.Like;
import top.wshape1.shiziapi.project.feign.SearchFeignService;
import top.wshape1.shiziapi.project.mapper.LikeMapper;
import top.wshape1.shiziapi.project.service.LikeService;
import top.wshape1.shiziapi.project.service.ProjectService;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author Wshape1
 * @description 针对表【t_project_like】的数据库操作Service实现
 * @since 2023-11-22 15:47:55
 */
@Service
@Slf4j
public class LikeServiceImpl extends ServiceImpl<LikeMapper, Like>
        implements LikeService {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;


    @Resource
    private ThreadPoolExecutor threadPoolExecutor;

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Override
    public void like(Long projectId, Long userId) {

        String likeSetName = RedisConstant.PROJECT_LIKE_SET_KEY + projectId;
        String noteLikeSetName = RedisConstant.PROJECT_NOTE_LIKE_KEY + projectId;
        String noteUnlikeSetName = RedisConstant.PROJECT_NOTE_UNLIKE_KEY + projectId;

        DefaultRedisScript<Long> script = new DefaultRedisScript<>();
        script.setResultType(Long.class);
        script.setScriptSource(new ResourceScriptSource(new ClassPathResource("lua/likeProject.lua")));
        Long execute = redisTemplate.execute(script, List.of(likeSetName, noteLikeSetName, noteUnlikeSetName), userId);

        if (execute != null && execute == 1)
            CompletableFuture.runAsync(() -> {
//                searchFeignService.likePlusOrReduce("plus", projectId);
                ProjectSearch projectSearch = new ProjectSearch();
                projectSearch.setId(projectId);
                projectSearch.setOperate(4);
                projectSearch.setUpdateTime(new Date());
                rabbitTemplate.convertAndSend(
                        RabbitMqConfig.SHIZIAPI_PROJECT_ELASTIC_EXCHANGE,
                        RabbitMqConfig.SHIZIAPI_PROJECT_ELASTIC_BINDING,
                        projectSearch
                );
            }, threadPoolExecutor);

    }

    @Override
    public void unlike(Long projectId, Long userId) {
        String likeSetName = RedisConstant.PROJECT_LIKE_SET_KEY + projectId;
        String noteLikeSetName = RedisConstant.PROJECT_NOTE_LIKE_KEY + projectId;
        String noteUnlikeSetName = RedisConstant.PROJECT_NOTE_UNLIKE_KEY + projectId;

        DefaultRedisScript<Long> script = new DefaultRedisScript<>();
        script.setResultType(Long.class);
        script.setScriptSource(new ResourceScriptSource(new ClassPathResource("lua/unlikeProject.lua")));
        Long execute = redisTemplate.execute(script, List.of(likeSetName, noteLikeSetName, noteUnlikeSetName), userId);

        if (execute != null && execute == 1)
            CompletableFuture.runAsync(() -> {
//                searchFeignService.likePlusOrReduce("reduce", projectId);
                ProjectSearch projectSearch = new ProjectSearch();
                projectSearch.setId(projectId);
                projectSearch.setOperate(5);
                projectSearch.setUpdateTime(new Date());
                rabbitTemplate.convertAndSend(
                        RabbitMqConfig.SHIZIAPI_PROJECT_ELASTIC_EXCHANGE,
                        RabbitMqConfig.SHIZIAPI_PROJECT_ELASTIC_BINDING,
                        projectSearch
                );
            }, threadPoolExecutor);

    }

    @Override
    public long countLike(Long projectId) {

        Long size = redisTemplate.opsForSet().size(RedisConstant.PROJECT_LIKE_SET_KEY + projectId);

        return size == null ? 0 : size;

    }

    @Override
    public List<Boolean> isLike(List<Long> projectIdList, Long userId) {
        return projectIdList.stream().map(projectId -> {
            Boolean b = redisTemplate.opsForSet().isMember(RedisConstant.PROJECT_LIKE_SET_KEY + projectId, userId);
            return b != null && b;
        }).toList();
    }


}




